/**
 *
 */
package com.lzx.applib.viewpager;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.CornerPathEffect;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.LinearLayout;
import android.widget.Scroller;
import android.widget.TextView;

import com.lzx.applib.R;
import com.lzx.applib.utils.DpSpDip2Px;
import com.lzx.applib.utils.LinearGradientUtil;
import com.lzx.applib.utils.LogUtil;


/**
 * @author Lzx
 */
public class ViewPagerIndicator extends LinearLayout implements OnPageChangeListener {

    private static final String TAG = "ViewPagerIndicator";

    ViewPager mViewPager;

    private Paint mPaint;
    private Path mPath;
    private float mLineHeight;
    private float mLineWidth;
    private boolean autoLineWidth = false;
    private int minLineWidth = -1;
    private LinearGradientUtil linearGradientUtil;

    private int mInitTranslationX;
    private float mTranslationX;

    private static final int DEFAULT_TAB_COUNT = 4;
    private int mTabVisibleCount = DEFAULT_TAB_COUNT;

    private int COLOR_TEXT_SELECTED = Color.RED;
    private int COLOR_TEXT_NORMAL = Color.BLACK;
    private int TEXT_SIZE = 16;

    private int COLOR_LINE = Color.RED;

    Scroller mScroller;
    GestureDetector gestureDetector;
    boolean changeByClick = false;
    boolean init = false;
    float currentPathWidth;

    public ViewPagerIndicator(Context context) {
        this(context, null);
    }

    public ViewPagerIndicator(Context context, AttributeSet attrs) {
        super(context, attrs);
        LogUtil.d(TAG, "ViewPagerIndicator");
        setOrientation(HORIZONTAL);
        mScroller = new Scroller(context);
        gestureDetector = new GestureDetector(context, new GestureListener());

        {
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ViewPagerIndicator);
            float lineHeight = a.getDimensionPixelSize(R.styleable.ViewPagerIndicator_lineHeight, 10);
            float lineWidth = a.getDimensionPixelSize(R.styleable.ViewPagerIndicator_lineWidth, 0);
            float textSize = a.getDimensionPixelSize(R.styleable.ViewPagerIndicator_textSize, TEXT_SIZE);
            int textSelectedColor = a.getColor(R.styleable.ViewPagerIndicator_textSelectedColor, COLOR_TEXT_SELECTED);
            int lineColor = a.getColor(R.styleable.ViewPagerIndicator_lineColor, textSelectedColor);
            int textUnselectedColor = a.getColor(R.styleable.ViewPagerIndicator_textUnselectedColor, COLOR_TEXT_NORMAL);
            int visibleCount = a.getInt(R.styleable.ViewPagerIndicator_tabVisibleCount, DEFAULT_TAB_COUNT);
            boolean autoLineWidth = a.getBoolean(R.styleable.ViewPagerIndicator_autoLineWidth, false);
            minLineWidth = a.getDimensionPixelSize(R.styleable.ViewPagerIndicator_minLineWidth, -1);
            a.recycle();

            mTabVisibleCount = visibleCount;
            COLOR_TEXT_NORMAL = textUnselectedColor;
            COLOR_TEXT_SELECTED = textSelectedColor;
            COLOR_LINE = lineColor;
            TEXT_SIZE = DpSpDip2Px.getInstance().px2sp(textSize);
            mLineHeight = lineHeight;
            mLineWidth = lineWidth;
            this.autoLineWidth = autoLineWidth;
        }

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor((COLOR_LINE));
        ;
        mPaint.setStyle(Style.FILL);
        mPaint.setPathEffect(new CornerPathEffect(3));
        linearGradientUtil = new LinearGradientUtil(COLOR_TEXT_NORMAL, COLOR_TEXT_SELECTED);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        LogUtil.d(TAG, "onSizeChanged() called with: w = [" + w + "], h = [" + h + "], oldw = [" + oldw + "], oldh = [" + oldh + "]");
        mInitTranslationX = 0;
        resetPath();
    }

    private void resetPath() {
        if (mPath == null) {
            mPath = new Path();
        } else {
            mPath.reset();
        }

        float tabWidth = getTabWidth();
        float lineWidth = getLineWidth();
        float dW = (tabWidth - lineWidth) / 2;

        mPath.moveTo(dW, 0);
        mPath.lineTo(tabWidth-dW, 0);
        mPath.lineTo(tabWidth-dW, -mLineHeight);
        mPath.lineTo(dW, -mLineHeight);
        mPath.close();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        LogUtil.d(TAG, "onDraw");
        if (!init) {
            init();
        }
        super.onDraw(canvas);
    }

    public void init() {
        LogUtil.d(TAG, "init1");
        if (mViewPager == null || mViewPager.getAdapter() == null) return;
        LogUtil.d(TAG, "init2");
        init = true;
        initTitleView();
        highLightTextView(mViewPager.getCurrentItem());
        scroll(mViewPager.getCurrentItem(), 0);
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        LogUtil.d(TAG, "dispatchDraw");
        canvas.save();
        canvas.translate(mInitTranslationX + mTranslationX, getHeight() + 1);
        canvas.drawPath(mPath, mPaint);
        canvas.restore();

        super.dispatchDraw(canvas);
    }

    public void setViewPager(ViewPager viewPager) {
        mViewPager = viewPager;
        mViewPager.addOnPageChangeListener(this);
    }

    public void initTitleView() {
        LogUtil.d(TAG, "initTitleView", mViewPager.getAdapter().getCount());
        this.removeAllViews();
        for (int i = 0; i < mViewPager.getAdapter().getCount(); i++) {
            String title = mViewPager.getAdapter().getPageTitle(i).toString();
            LogUtil.d(TAG, "initTitleView", title);
            TextView textView = genTextView();
            textView.setText(title);
            addView(textView);
        }
        setItemClick();
    }

    private TextView genTextView() {
        TextView textView = new TextView(getContext());
        LayoutParams lp = new LayoutParams(0, LayoutParams.MATCH_PARENT);
        lp.width = (int) getTabWidth();
        textView.setPadding(lp.width/16, 0, lp.width/16, 0);
        textView.setLayoutParams(lp);
        textView.setTextColor(COLOR_TEXT_NORMAL);
        textView.setGravity(Gravity.CENTER);
        textView.setTextSize(TEXT_SIZE);
        textView.setSingleLine();
        textView.setEllipsize(TruncateAt.MARQUEE);
        textView.setLayoutParams(lp);

        return textView;
    }

    private void setItemClick() {
        for (int i = 0; i < getChildCount(); i++) {
            final View view = getChildAt(i);
            final int index = i;
            view.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    changeByClick = true;
                    scroll(index, 0);
                    mViewPager.setCurrentItem(index, true);
                    LogUtil.d(TAG, view.getWidth(), view.getHeight(), ((TextView)view).getText());
                }
            });
        }
    }

    private float getItemLineWidth(int position) {
        TextView tv = (TextView) getChildAt(position);
        float width = tv.getPaint().measureText(tv.getText().toString());
        return Math.max(minLineWidth, width);
    }

    private void resetTextViewColor() {
        for (int i = 0; i < getChildCount(); i++) {
            View view = getChildAt(i);
            if (view instanceof TextView) {
                ((TextView) view).setTextColor(COLOR_TEXT_NORMAL);
                ((TextView) view).setSelected(false);
            }
        }
    }

    private void highLightTextView(int position) {
        View view = getChildAt(position);
        if (view instanceof TextView) {
            ((TextView) view).setTextColor(COLOR_TEXT_SELECTED);
            ((TextView) view).setSelected(true);
        }
    }

    private float getTabWidth() {
        return (float) (1.0 * getWidth() / mTabVisibleCount);
    }

    private float getLineWidth() {
        if (autoLineWidth) {
            return currentPathWidth;
        }
        return mLineWidth <=0 ? getTabWidth() : mLineWidth;
    }

    public void setVisibleTabCount(int count) {
        mTabVisibleCount = count;
    }

    private void scroll(int position, float offset) {
        float tabWidth = getTabWidth();
        mTranslationX = (offset + position) * tabWidth;
        setLineWidth(position, offset);
        setTextColor(position, offset);

        float curPosition = position + offset;
        float scrollPosition = 0;
        if (getCount() > mTabVisibleCount) {
            int scrollX = 0;
            if (curPosition < (mTabVisibleCount-1)/2f) {
                scrollX = 0;
            }
            else {
                scrollPosition = curPosition - (mTabVisibleCount-1)/2f;
                scrollX = (int) (scrollPosition * tabWidth);
            }

            scrollTo(scrollX, 0);
        }
        invalidate();
    }

    private void setLineWidth(int position, float offset) {
        if (autoLineWidth){
            if (position < getChildCount()-1) {
                float width1 = getItemLineWidth(position);
                float width2 = getItemLineWidth(position+1);
                currentPathWidth = width1 + offset * (width2 - width1);
                resetPath();
            }
        }
    }

    private void setTextColor(int position, float offset) {
        if (position < getChildCount()-1) {
            int colorSelected = linearGradientUtil.getColor(offset);
            int colorUnSelected = linearGradientUtil.getColor(1-offset);

            TextView tv = (TextView) getChildAt(position);
            tv.setTextColor(colorUnSelected);
            TextView tv2 = (TextView) getChildAt(position+1);
            tv2.setTextColor(colorSelected);
        }
    }

    @Override
    public void scrollTo(int x, int y) {
        int min = 0;
        int max = (int) (getTabWidth() * getChildCount() - getWidth());
        x = Math.max(Math.min(max, x), min);
        super.scrollTo(x, 0);
    }

    public int getCount() {
        return mViewPager.getAdapter().getCount();
    }

    float downX = 0;
    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        int action = event.getAction();
        float x = event.getX();

        gestureDetector.onTouchEvent(event);
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                downX = x;
                break;
            case MotionEvent.ACTION_MOVE:
                if (Math.abs(x - downX) >= ViewConfiguration.get(getContext()).getScaledTouchSlop())
                    return true;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                break;

            default:
                break;
        }
        return super.onInterceptTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
//        LogUtil.d(TAG, "onTouchEvent() called with: event = [" + event + "]");
        gestureDetector.onTouchEvent(event);
        return true;
    }


    public class GestureListener extends GestureDetector.SimpleOnGestureListener {

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
//            LogUtil.d(TAG, "onScroll() called with:  distanceX = [" + distanceX + "], distanceY = [" + distanceY + "]");
            scrollBy((int) distanceX, 0);
            mScroller.startScroll(getScrollX(), getScrollY(), (int)distanceX, (int)distanceY);
            return false;
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
//            LogUtil.d(TAG, "onFling() called with: velocityX = [" + velocityX + "], velocityY = [" + velocityY + "]");
            mScroller.fling(getScrollX(), 0, (int)-velocityX, 0, 0, (int) (getTabWidth()*getCount()),0, 0);
            return false;
        }
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        if (!mScroller.isFinished()) {
            mScroller.computeScrollOffset();
            scrollTo(mScroller.getCurrX(), 0);
            postInvalidate();
        }
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        if (state == ViewPager.SCROLL_STATE_IDLE) {
            changeByClick = false;
            scroll(mViewPager.getCurrentItem(), 0);
        }
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        LogUtil.d(TAG, "onPageScrolled() called with: position = [" + position + "], positionOffset = [" + positionOffset + "], positionOffsetPixels = [" + positionOffsetPixels + "]");
        if (!changeByClick)
            scroll(position, positionOffset);
    }

    @Override
    public void onPageSelected(int position) {
//        LogUtil.d(TAG, "onPageSelected() called with: position = [" + position + "]");
        resetTextViewColor();
        highLightTextView(position);
    }

}
